﻿#pragma once
#ifndef ICP_SERVICE_H
#define ICP_SERVICE_H

#include <ppl.h>

#include <mutex>

#include "BasAirport.h"
#include "BasAirportBreak.h"
#include "BasAirportNight.h"
#include "BasAirportTransfer.h"
#include "BasFleet.h"
#include "BasPattern.h"
#include "BasResLimit.h"
#include "HRCrew.h"
#include "ICPLabel.h"
#include "ICPNode.h"
#include "ICPPairingConfig.h"
#include "ICPRule.h"
#include "ICPUtility.h"
#include "SchDuty.h"
#include "SchLeg.h"
#include "SchPairing.h"

struct PairingPath {
  private:
    string _baseCode;
    bool _isI;
    ICPNode* _startNode;
    ICPNode* _endNode;

  public:
    PairingPath(string baseCode, ICPNode* startNode, ICPNode* endNode, bool isI)
        : _baseCode(baseCode), _startNode(startNode), _endNode(endNode), _isI(isI) {}
    ~PairingPath() {}

    string getBaseCode() { return _baseCode; }
    bool isI() { return _isI; }
    ICPNode* getStartNode() { return _startNode; }
    ICPNode* getEndNode() { return _endNode; }
};

class ICPService {
  private:
    std::mutex mtx; // 冲突锁

    map<string, BasFleet*> _fleetMap;
    vector<BasAirport*> _airportList;
    map<string, HrCrew*> _hrCrewMap;
    vector<SchLeg*> _legList;

    vector<SchDuty*> _dutyList;
    vector<SchPairing*> _pairingList;
    vector<SchPairing*> _pairingListPattern;

    vector<ICPNode*> _nodeList;
    vector<SchPairing*> _betterPairingList;

    vector<SchLeg*> _slnDeadheadLegList;
    vector<SchPairing*> _slnPairingList;

    double getProfit(string baseCode, ICPLabel* label, SchDuty* duty);

  public:
    ICPService();
    ~ICPService();

    // 机型表
    void setFleetMap(string acType, BasFleet* fleet) { _fleetMap[acType] = fleet; }
    string getAcTypeCrew(string acType) {
        if (_fleetMap.count(acType) == 0) {
            return acType;
        }
        return _fleetMap[acType]->getAcTypeCrew();
    }

    void setAirportList(vector<BasAirport*> airports) { _airportList = airports; }
    vector<BasAirport*> getAirportList() { return _airportList; }

    void pushHrCrew(HrCrew* hrcrew) { _hrCrewMap[hrcrew->getPCode()] = hrcrew; }
    HrCrew* getHrCrew(string pCode) { return _hrCrewMap.count(pCode) == 0 ? NULL : _hrCrewMap[pCode]; }
    map<string, HrCrew*> getHrCrewMap() { return _hrCrewMap; }

    void setLegList(vector<SchLeg*> legs) { _legList = legs; }
    void insertLegList(vector<SchLeg*> legs) { _legList.insert(_legList.end(), legs.begin(), legs.end()); }
    vector<SchLeg*> getLegList() { return _legList; }
    SchLeg* newVALeg(SchLeg* leg);

    void setSlnDeadheadLeglist(vector<SchLeg*> slnDeadheadLegList) { _slnDeadheadLegList = slnDeadheadLegList; }
    vector<SchLeg*> getSlnDeadheadLegList() { return _slnDeadheadLegList; }

    void setSlnPairingList(vector<SchPairing*> slnPairinglist) { _slnPairingList = slnPairinglist; }
    vector<SchPairing*> getSlnPairingList() { return _slnPairingList; }

    vector<SchDuty*> getDutyList() { return _dutyList; }
    vector<SchPairing*> getPairingList() { return _pairingList; }
    vector<SchPairing*> getBetterPairingList() { return _betterPairingList; }

    void sortLegList() { sort(_legList.begin(), _legList.end(), SchLeg::cmpByTime); }

    SchPairing* convertPairing(string name, vector<SchLeg*> legs, string baseCode);

    BasAirport* getAirport(string code3);
    SchLeg* getLeg(string flightId);
    SchLeg* getSolnDeadheadLeg(string flightId);

    void init();
    void initResLimit();
    void initNodeList();
    void genDutyList();
    void genAcTypeCrewComb(const vector<std::string>& acTypeCrews, int N, std::vector<string>& combs,
                           string current = "");
    vector<SchDuty*> genDutyListBase();
    vector<SchDuty*> genDutyListRest();
    void genDutyList(SchDuty* crtDuty, SchLeg* leg);

    void computeDutyCost();
    void updateDutyRedCost();

    vector<SchPairing*> genPairingListByDuty();
    void genPairingListByPattern();
    vector<SchPairing*> getPairingListByPattern() { return _pairingListPattern; }
    void genBetterPairingList();
    void genBetterPairingListBase();
    vector<SchPairing*> genBetterPairingList(PairingPath* pairingPath);

    bool dominateLabel(vector<ICPLabel*>& pLabelList, ICPLabel* pLabel);

    static double getHardAirportScore(vector<BasAirport*> airportList);
    vector<SchPairing*> genUnSolvePairing(); // 将未组的单班（国际班）生成任务环
    vector<SchPairing*> genPairingB();       // 生成备份任务环
};

#endif // !ICP_SERVICE_H